﻿using System;
using System.Diagnostics;
using StockAccessors;
using StockEngine.Historical;
using StockEngine.RealTime;
using Utils.Wpf;

namespace StockAnalyst2
{
	internal class MainStatusBarVM : ViewModelBase, IDisposable
	{
		#region Attributes

		private readonly IStockDataAccessor _accessor;
		private readonly AcquisitionSystem _acquisitionSystem;
		private readonly HistoricalSystem _historicalSystem;

		#endregion

		#region Properties

		public string LastSchedulerCheck
		{
			get
			{
				// Format as 00/00/0000 00:00:00
				if (_acquisitionSystem.Information.LastSchedulerCheck == null)
				{
					return null;
				}
				else
				{
					return _acquisitionSystem.Information.LastSchedulerCheck.Value.ToString("dd/MM/yyyy HH:mm:ss");	
				}
			}
		}

		public string LastDataReceived
		{
			get
			{
				if (_accessor.Information.LastDataReceived == null)
				{
					return null;
				}
				else
				{
					// Format as 00/00/0000 00:00:00
					return _accessor.Information.LastDataReceived.Value.ToString("dd/MM/yyyy HH:mm:ss");	
				}
			}
		}

		public string DataRefreshes
		{
			get
			{
				// Format with 00000 (5) zeros	 
				return _accessor.Information.ReadCycles.ToString("00000");
			}
		}

		public string Reconnections
		{
			get
			{
				// Format with 000 (3) zeros
				return _accessor.Information.Reconnections.ToString("000");
			}
		}

		public AcquisitionSystemState RealTimeCaptureState
		{
			get
			{
				return _acquisitionSystem.Information.State;
			}
		}

		public HistoricalSystemState HistoricalSystemState
		{
			get
			{
				return _historicalSystem.State;
			}
		}

		public int EngineStarted
		{
			get
			{
				return _acquisitionSystem.Information.CaptureStarted ? 1 : 0;
			}
		}

		public int Connected
		{
			get
			{
				return _accessor.Information.Connected ? 1 : 0;
			}
		}

	    public int SkippedItems
	    {
	        get
	        {
                return _acquisitionSystem.Information.SkippedItems;
	        }
	    }

		#endregion

		#region Public Methods

		public MainStatusBarVM(IStockDataAccessor accessor, AcquisitionSystem acquisitionSystem, HistoricalSystem historicalSystem)
		{
			_accessor = accessor;
			_accessor.Information.PropertyChanged += this.Accessor_PropertyChanged; // Disposed
			
			_acquisitionSystem = acquisitionSystem;
			_acquisitionSystem.Information.PropertyChanged += this.AcquisitionSystem_PropertyChanged; // Disposed

			_historicalSystem = historicalSystem;
			_historicalSystem.PropertyChanged += this.HistoricalSystem_PropertyChanged; // Disposed
		}

		#endregion

		#region Event Handlers

		private void Accessor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			if(e.PropertyName == "ReadCycles")
			{
				base.OnPropertyChanged("DataRefreshes");
			}
			else if (e.PropertyName == "LastDataReceived")
			{
				base.OnPropertyChanged("LastDataReceived");
			}
			else if (e.PropertyName == "Connected")
			{
				base.OnPropertyChanged(e.PropertyName);	
			}
			else if(e.PropertyName == "Reconnections")
			{
				base.OnPropertyChanged(e.PropertyName);	
			}
			else
			{
				Debug.WriteLine("Ignored accessor property changed: " + e.PropertyName);
			}
		}

		private void AcquisitionSystem_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			if (e.PropertyName == "LastSchedulerCheck")
			{
				base.OnPropertyChanged(e.PropertyName);
			}
			else if (e.PropertyName == "CaptureStarted")
			{
				base.OnPropertyChanged("EngineStarted");	
			}
			else if (e.PropertyName == "State")
			{
				base.OnPropertyChanged("RealTimeCaptureState");
			}
            else if (e.PropertyName == "SkippedItems")
            {
                base.OnPropertyChanged("SkippedItems");
            }
            else
			{
				Debug.WriteLine("Ignored acquisition system property changed: " + e.PropertyName);
			}
		}

		private void HistoricalSystem_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			if (e.PropertyName == "State")
			{
				base.OnPropertyChanged("HistoricalSystemState");
			}
		}

		#endregion

		#region IDisposable

		protected bool Disposed { get; private set; }

		private void Dispose(bool disposing)
		{
			if (!this.Disposed)
			{
				this.InternalDispose(disposing);
			}

			this.Disposed = true;
		}

		protected virtual void InternalDispose(bool disposing)
		{
			if (disposing)
			{
				_accessor.Information.PropertyChanged -= this.Accessor_PropertyChanged;
				_acquisitionSystem.Information.PropertyChanged -= this.AcquisitionSystem_PropertyChanged;
				_historicalSystem.PropertyChanged -= this.HistoricalSystem_PropertyChanged;
			}

			// Dispose here only unmanaged objects 
			// Don’t use managed objects here because maybe 
			// they have been finalized already
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		~MainStatusBarVM()
		{
			this.Dispose(false);
		}

		#endregion
	}
}
